#include <QFileInfo>
#include <QByteArray>
#include <QTextCodec>
#include <QJsonParseError>
#include <QJsonArray>
#include <QJsonObject>
extern "C"
{
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/avutil.h"
    #include "libavutil/mem.h"
    #include "libavutil/fifo.h"
    #include "libswscale/swscale.h"
}
#include "playlistmodel.h"

PlayListModel::PlayListModel(QObject *parent)
    :QAbstractListModel(parent)
    ,m_data(QMap<int,QVariantMap>())
{
    m_playList = new QMediaPlaylist();
}

bool PlayListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent){
    return QAbstractListModel::dropMimeData(data,action,row,column,parent);
}

Qt::ItemFlags PlayListModel::flags(const QModelIndex &index) const
{
    return Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsDragEnabled;
}

QModelIndex PlayListModel::index(int row, int column, const QModelIndex &parent) const
{
    return m_playList && !parent.isValid()
            && row >= 0 && row < m_playList->mediaCount()
        ? createIndex(row, column)
        : QModelIndex();
}

int PlayListModel::rowCount(const QModelIndex &parent) const
{
    return m_playList&&!parent.isValid()?m_playList->mediaCount():0;
}

 QVariant PlayListModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();
    if(role>=TitleRole&&role<=AlbumRole){
        QVariantMap item = m_data[index.row()];
        if(!item.contains("islocal")){
            switch(role){
                case TitleRole:return item["name"].toString();break;
                case ArtistRole:return item["alias"].toString();break;
                case AlbumRole:return item["album_id"].toString();break;
            }
        }else{
            QUrl location = m_playList->media(index.row()).canonicalUrl();
            if(role == TitleRole){
                return QFileInfo(location.path()).fileName();
            }
            //localFile
            QByteArray localFile = location.toLocalFile().toUtf8();
            char *urlchar = localFile.data();
            av_register_all();
            AVFormatContext *ic = avformat_alloc_context();
            avformat_open_input(&ic, urlchar, NULL, NULL);
            avformat_find_stream_info(ic, NULL);
            AVDictionaryEntry *m = NULL;
            QTextCodec * codec = QTextCodec::codecForName ( "GBK" );
            if(role == ArtistRole){
                m=av_dict_get(ic->metadata,"artist",m,0);
                return m?codec->toUnicode(m->value):"未知";
            }
            if(role == AlbumRole){
                m=av_dict_get(ic->metadata,"album",m,0);
                return m?codec->toUnicode(m->value):"未知";
            }
            avformat_free_context(ic);
        }
    }
    return QVariant();
}

 static bool isPlaylist(const QUrl &url) // Check for ".m3u" playlists.
 {
      if (!url.isLocalFile())
          return false;
      const QFileInfo fileInfo(url.toLocalFile());
      return fileInfo.exists() && !fileInfo.suffix().compare(QLatin1String("m3u"), Qt::CaseInsensitive);
 }

 void PlayListModel::addToPlaylist(const QList<QUrl> urls)
 {
     beginResetModel();
     foreach (const QUrl &url, urls) {
         if (isPlaylist(url)){
            m_playList->load(url);
         }else{
            m_playList->addMedia(url);
         }
         QVariantMap item =  QVariantMap();
         item.insert("islocal",1);
         int lastKey = m_data.lastKey();
         m_data[++lastKey] = item;
     }
     endResetModel();
 }
void PlayListModel::setPlayList(QMediaPlaylist *playlist)
{
    beginResetModel();
    m_playList = playlist;
    endResetModel();
}
QVariant PlayListModel::get(int row,InfoRoles role){
    QModelIndex index = getIndex(row);
    return data(index,role);
}

void PlayListModel::jump(int row)
{
    QModelIndex index = getIndex(row);
    if (index.isValid()&&m_playList->currentIndex() != row) {
        m_playList->setCurrentIndex(index.row());
        emit playListChanged(row);
    }
}

int PlayListModel::getCurrentIndex()
{
    int row = m_playList->currentIndex();
    return row;
}
void PlayListModel::next()
{
    int row = m_playList->nextIndex();
    jump(row);
}

void PlayListModel::previous()
{

    int row = m_playList->previousIndex();
    jump(row);
}
void PlayListModel::setPlayListFromHttp(QString url)
{
    QUrl qurl(url);
    QNetworkRequest req(qurl);
    m_reply = m_nam.get(req);
    connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(onEror(QNetworkReply::NetworkError)));
    connect(m_reply,SIGNAL(finished()),this,SLOT(onFinished()));
}
QModelIndex PlayListModel::getIndex(int row)
{
    return createIndex(row,0);
}

QHash<int, QByteArray> PlayListModel::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[TitleRole] = "title";
    roles[ArtistRole] = "artist";
    roles[AlbumRole] = "album";
    return roles;
}

void PlayListModel::onEror(QNetworkReply::NetworkError code)
{
    qDebug()<<code;
}

void PlayListModel::onFinished()
{
    beginResetModel();
    int status = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<status;
    if(m_reply->error() == QNetworkReply::NoError){
        QByteArray data = m_reply->readAll();
        QJsonParseError jsonpe;
        QJsonDocument json = QJsonDocument::fromJson(data, &jsonpe);
        if(jsonpe.error == QJsonParseError::NoError)
        {
            if(json.isObject()){
                QJsonObject res = json.object();
                QJsonArray items = res["items"].toArray();
                for(int i=0;i<items.size();i++){
                   QJsonObject item = items[i].toObject();
                   m_data.insert(i,item.toVariantMap());
                   QString thisurl = QString("http://www.music.test/uploads/%1").arg(item["mp3_url"].toString());
                   m_playList->addMedia(QUrl(thisurl));
                }
            }
        };
    }
    endResetModel();
}

